package com.kubepartners.impactmodel.model;
import java.util.Iterator;
import java.util.Set;

import org.jgrapht.graph.DefaultDirectedGraph;

public class Graph extends DefaultDirectedGraph<Node, Edge> {
	private static final long serialVersionUID = 1L;
	private static final double decimals = 6.0;
    
	//graph state machine: "structure", "measured", "results"
    private String graph_state;
	
	//properties that implement error state for the Node;
	private boolean cyclic=false;

    
	public Graph(Class<? extends Edge> edge) {
		super(edge);
		this.cyclic=false;
		this.graph_state="structure";
	}
	
	public static double round(double capacity) {
		int number = (int) Math.pow(10.0, decimals);
		int new_capacity = (int) (capacity*number);
		return (double) new_capacity/number;
	}

	public Node findNodeById(String id) {
		Iterator<Node> it = vertexSet().iterator();
		while (it.hasNext()) {
			Node n = it.next();
			if (n.getId().equals(id)) {
				return n;
			}
		}
		return null;
	}
	
	public Node findNodeByLabel(String id) {
		Iterator<Node> it = vertexSet().iterator();
		while (it.hasNext()) {
			Node n = it.next();
			if (n.getLabel().equals(id)) {
				return n;
			}
		}
		return null;
	}

	public Node getRoot() {
		Iterator<Node> it = vertexSet().iterator();
		while (it.hasNext()) {
			Node node = it.next();
			if (outgoingEdgesOf(node).size() == 0) {
				return node;
			}
		}
		return null;
	}
	
	public boolean isLeaf(Node node) {
		return (incomingEdgesOf(node).size() == 0);
	}

	public boolean isCyclic() {
		return cyclic;
	}

	public void setCyclic(boolean cyclic) {
		this.cyclic = cyclic;
	}

	public String getGraph_state() {
		return graph_state;
	}

	public void setGraph_state(String graph_state) {
		double vertexCapacity_default =1;
		double inducedCapacity_default =-1;
		double deliveredCapacity_default =-1;
		
		if(graph_state=="structure"){
			//bring to defaults vertex, induced and delivered capacities
			Set<Node> nodes=this.vertexSet();
			Iterator<Node> n =nodes.iterator();
			
			while(n.hasNext()){
				Node node=n.next();
				node.setVertexCapacity(vertexCapacity_default);
				node.setDeliveredCapacity(deliveredCapacity_default);
				node.setInducedCapacity(inducedCapacity_default);
				
			}
			
		}
		else if(graph_state=="measured"){
			//bring to defaults induced and delivered capacities
			Set<Node> nodes=this.vertexSet();
			Iterator<Node> n =nodes.iterator();
			
			while(n.hasNext()){
				Node node=n.next();
				node.setDeliveredCapacity(deliveredCapacity_default);
				node.setInducedCapacity(inducedCapacity_default);
				
			}
			
		}
		this.graph_state=graph_state;
	}

	@Override
	public boolean addEdge(Node source, Node target, Edge edge) {
		edge.setStartNode(source);
		edge.setEndNode(target);
		return super.addEdge(source, target, edge);
	}
	
	
	public Edge findEdgeById(String id){
		Iterator<Edge> it = edgeSet().iterator();
		while (it.hasNext()) {
			Edge e = it.next();
			if (e.getId().equals(id)) {
				return e;
			}
		}
		return null;
	}
	
}
